package tinp.endpoint;

import javax.annotation.Nullable;
import javax.inject.Named;

import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.response.CollectionResponse;
import com.google.api.server.spi.response.ConflictException;
import com.google.api.server.spi.response.NotFoundException;
import com.google.api.server.spi.response.UnauthorizedException;
import com.google.appengine.api.datastore.Cursor;
import com.google.appengine.api.users.User;
import com.googlecode.objectify.cmd.Query;
import tinp.entity.Post;
import tinp.entity.PostContent;

import java.util.List;

import static tinp.entity.OfyService.ofy;

/**
 * @author Tin Pham
 * @since 8/11/2014.
 */
@Api(
		name = "papi",
		description = "Post API",
		version = "v1",
		clientIds = {Ids.WEB_CLIENT_ID, Ids.ANDROID_CLIENT_ID, Ids.IOS_CLIENT_ID},
		audiences = {Ids.ANDROID_AUDIENCE}
)
public class PostEndpoint {

	private static int DEFAULT_PAGE_SIZE = 10;

	public CollectionResponse<Post> listPost(@Nullable @Named("cursor") String cursorString, @Nullable @Named("limit") Integer limit) {
		if (limit == null) {
			limit = DEFAULT_PAGE_SIZE;
		}
		Query<Post> query;
		if (limit == 0) {
			query = ofy().load().type(Post.class).order("-date");
		} else if (cursorString == null || cursorString == "") {
			query = ofy().load().type(Post.class).order("-date").limit(limit);
		} else {
			query = ofy().load().type(Post.class).order("-date").limit(limit).startAt(Cursor.fromWebSafeString(cursorString));
		}
		List<Post> retList = query.list();
		String retCursor = query.iterator().getCursor().toWebSafeString();
		return new CollectionResponse.Builder<Post>().setItems(retList).setNextPageToken(retCursor).build();
	}

	public Post getPost(@Named("id") Long id) throws NotFoundException {
		Post post = ofy().load().type(Post.class).id(id).get();
		if (post == null) {
			throw new NotFoundException("The post with ID " + id + " is not found.");
		}
		PostContent postContent = ofy().load().type(PostContent.class).id(id).get();
		if (postContent == null) {
			throw new NotFoundException("The post with ID " + id + " is not found.");
		}
		post.setContent(postContent.getContent()); // response the post with its content
		return post;
	}

	public Post insertPost(Post post) throws ConflictException {
		Post existingPost = ofy().load().type(Post.class).id(post.getId()).get();
		if (existingPost != null) {
			throw new ConflictException("The post with ID " + post.getId() + " already exists");
		}
		PostContent postContent = new PostContent();
		postContent.setContent(post.getContent());
		// clear the post content, save its content in post content
		post.setContent("");
		ofy().save().entity(post).now();
		postContent.setId(post.getId()); // save post content with the same its post ID
		ofy().save().entity(postContent).now();
		return post;
	}

	public Post updatePost(@Named("id") Long id, Post post) throws NotFoundException {
		Post targetPost = ofy().load().type(Post.class).id(id).get();
		if (targetPost == null) {
			throw new NotFoundException("The post with ID " + id + " is not found.");
		}
		PostContent targetPostContent = ofy().load().type(PostContent.class).id(id).get();
		if (targetPostContent == null) {
			throw new NotFoundException("The post with ID " + id + " is not found.");
		}
		if (post.getTitle() != null) {
			targetPost.setTitle(post.getTitle());
		}
		if (post.getMeta() != null) {
			targetPost.setMeta(post.getMeta());
		}
		if (post.getDate() != null) {
			targetPost.setDate(post.getDate());
		}
		if (post.getAuthor() != null) {
			targetPost.setAuthor(post.getAuthor());
		}
		if (post.getContent() != null) {
			targetPostContent.setContent(post.getContent());
		}
		ofy().save().entity(targetPost).now();
		ofy().save().entity(targetPostContent).now();
		// response the updated post with its content
		post.setContent(targetPostContent.getContent());
		return post;
	}

	public void removePost(@Named("id") Long id, User user) throws UnauthorizedException, NotFoundException {
		if (user == null) {
			throw new UnauthorizedException("User is not valid.");
		}
		Post targetPost = ofy().load().type(Post.class).id(id).get();
		if (targetPost == null) {
			throw new NotFoundException("The post with ID " + id + " is not found.");
		}
		PostContent targetPostContent = ofy().load().type(PostContent.class).id(id).get();
		if (targetPostContent == null) {
			throw new NotFoundException("The post with ID " + id + " is not found.");
		}
		ofy().delete().entity(targetPost);
		ofy().delete().entity(targetPostContent);
	}
}
